using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using DomainModel.Abstract;
using DomainModel.Entities;

namespace WebSite.Controllers
{
    // The controller for dealing with views regarding the creation and
    // editing of job types and the ability to associate questions with them.
    [Authorize(Roles = "StaffingExpert")]
    public class JobsManagementController : Controller
    {
        // The database abstractions for the jobs, questions, questionnaireEntries, and positions.
        private IJobsRepository jobsRepository;
        private IQuestionsRepository questionsRepository;
        private IQuestionnaireEntriesRepository questionnaireEntriesRepository;
        private IPositionsRepository positionsRepository;

        // Constructor, it attachs the jobs repository, the questions repository, 
        // the questionnaireEntry repository, and the positions repository to the 
        // controller.
        public JobsManagementController(IJobsRepository jobsRepository, IQuestionsRepository questionsRepository,
                IQuestionnaireEntriesRepository questionnaireEntriesRepository, IPositionsRepository positionsRepository)
        {
            this.questionsRepository = questionsRepository;
            this.jobsRepository = jobsRepository;
            this.questionnaireEntriesRepository = questionnaireEntriesRepository;
            this.positionsRepository = positionsRepository;

            ViewData["questions"] = new List<Question>();
            TempData["error"] = "";
        }

        // This is just a wrapper for the query to get a job given an id.
        private Job GetJob(int jobID)
        {
            Job job = (from j in jobsRepository.Jobs
                       where j.JobID == jobID
                       select j).First();
            return job;
        }

        // This is just a wrapper for the query to get a question given an id.
        private Question GetQuestion(int questionID)
        {
            Question question = (from q in questionsRepository.Questions
                                 where q.QuestionID == questionID
                                 select q).First();
            return question;
        }

        // Provides list of jobs in repository as model to Index view.
        public ViewResult Index()
        {
            
            return View(jobsRepository.Jobs.ToList());
        }

        // Instantiates a new job and passes it to the Edit view.
        public ActionResult Create()
        {
            return View("Edit", new Job());
        }

        // Edit command for http get, returns a job given an id
        // and passes the job to the view.
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult Edit(int jobID)
        {
            Job job = GetJob(jobID);

            return View(job);
        }

        // Edit command for post, places a job from the view into
        // the repository.
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(Job job)
        {
            if (ModelState.IsValid)
            {
                jobsRepository.SaveJob(job);
                return RedirectToAction("Index");
            }
            else
            {
                return View(job);
            }
        }

        // The Http-Get for delete job. Provide job to be deleted
        // to the view.
        public ActionResult Delete(int jobID)
        {
            Job job = GetJob(jobID);

            return View(job);
        }

        // This deletes a job from the repository given a
        // id from the view. Also deletes any bridge entries between
        // the job and the questions. It will not delete anything if
        // there are any answeredQuestions pointing at the attached
        // questions or Positions pointing at the job.
        [AcceptVerbs(HttpVerbs.Post)]
        public RedirectToRouteResult Delete(int jobID, string confirmButton)
        {
            Job job = GetJob(jobID);

            if (job.Positions.Count > 0)
            {
                TempData["error"] = "Cannot delete this job. It has important archival data attached to it.";
                return RedirectToAction("Index");
            }

            foreach (QuestionnaireEntry qe in job.QuestionnaireEntries)
            {
                if (qe.AnsweredQuestions.Count > 0)
                {
                    TempData["error"] = "Cannot delete this job. It has important archival data attached to it.";
                    return RedirectToAction("Index");
                }
            }

            foreach (QuestionnaireEntry qe in questionnaireEntriesRepository.QuestionnaireEntries)
            {
                if (qe.JobID == jobID)
                {
                    questionnaireEntriesRepository.DeleteQuestionnaireEntry(qe);
                }
            }
            
            jobsRepository.DeleteJob(job);

            return RedirectToAction("Index");
        }

        // Get a list of Questions that are attached to a job
        // given a jobID.
        public List<Question> GetAttachedQuestions(int jobID)
        {
            Job job = GetJob(jobID);
            List<Question> questions = new List<Question>();
            foreach (int qid in job.QuestionnaireEntries.Select(od => od.QuestionID))
            {
                questions.Add(GetQuestion(qid));
            }

            return questions;
        }

        // Get a list of Questions that are not attached to a job
        // given a jobID.
        public List<Question> GetDetachedQuestions(int jobID)
        {
            var questionnaireEntries = (from qe in questionnaireEntriesRepository.QuestionnaireEntries
                                                   where qe.JobID == jobID
                                                   select qe);

            List<Question> questions = new List<Question>();
            foreach (Question q in questionsRepository.Questions)
            {
                bool shouldAdd = true;
                foreach (QuestionnaireEntry qe in questionnaireEntries)
                {
                    if (q.QuestionID == qe.QuestionID)
                        shouldAdd = false;
                }
                if (shouldAdd)
                    questions.Add(q);
            }

            return questions;
        }

        // View the questions attached to a job in a partial view 
        // given a jobID.
        public ActionResult ViewQuestions(int jobID)
        {
            ViewData["questions"] = GetAttachedQuestions(jobID);

            return PartialView("QuestionsTable", ViewData["questions"]);
        }

        // Open up the view that allows the user to attach and detach questions
        // from a job. It stores the jobID from the model for the next view
        // and seperates the questions that are attached to a job and not
        // attached to a job into two lists.
        public ViewResult AttachDetachQuestion(int jobID)
        {
            Job job = GetJob(jobID);
            ViewData["questions"] = GetDetachedQuestions(jobID);
            ViewData["attachedquestions"] = GetAttachedQuestions(jobID);
            TempData["currentjob"] = jobID;

            return View(job);
        }

        // Attach a question to a job. Builds a new QuestionnaireEntry
        // and stores it in the database.
        public ActionResult Attach(int questionID)
        {
            int jobID = (int)TempData["currentjob"];

            QuestionnaireEntry questionnaireEntry = new QuestionnaireEntry();
            questionnaireEntry.JobID = jobID;
            questionnaireEntry.QuestionID = questionID;
            questionnaireEntriesRepository.SaveQuestionnaireEntry(questionnaireEntry);

            return RedirectToAction("AttachDetachQuestion", new { jobID = jobID });
        }

        // Detaches a questions from a job. Finds the correct QuestionnaireEntry and
        // deletes it.
        public ActionResult Detach(int questionID)
        {
            int jobID = (int)TempData["currentjob"];

            QuestionnaireEntry questionnaireEntry = (from qe in questionnaireEntriesRepository.QuestionnaireEntries
                                                     where qe.QuestionID == questionID && qe.JobID == jobID
                                                     select qe).First();
            questionnaireEntriesRepository.DeleteQuestionnaireEntry(questionnaireEntry);

            return RedirectToAction("AttachDetachQuestion", new { jobID = jobID });
        }

        public ViewResult List()
        {
            return View(jobsRepository.Jobs.ToList());
        }
    }
}
